import { Canvas2DApplication } from "../ch3/Application";
import { Rectangle } from "../ch3/Math2d";

type Repeatition = "repeat" | "repeat-x" | "repeat-y" | "no-repeat";

// 字体 `FontStyle FontVariant FontWeight FontSize FontFamily`
// 字体样式
type FontStyle = "normal" | "italic" | "oblique";
// 字体变体
type FontVariant = "normal" | "small-caps";
// 字体粗细
type FontWeight = "normal" | "bold" | "bolder" | "lighter" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900";
// 字体大小 像素
type FontSize = "10px" | "12px" | "16px" | "18px" | "20px" | "24px" | "50%" | "75%" | "100%" | "125%" | "150%" | "xx-small" | "x-small" | "small" | "medium" | "large" | "x-large" | "xx-large";
// 字体系列
type FontFamily = "sans-serif" | "serif" | "courier" | "fantasy" | "monospace";

// 字体对齐
type TextAlign =
    "start"
    | "left"
    | "center"
    | "right"
    | "end"
type TextBaseline =
    'alphabetic'
    | 'hanging'
    | 'top'
    | 'middle'
    | 'bottom'
enum EImageFillType {
    STRETCH,  //缩放模式
    REPEAT,   //x,y重复
    REPEAT_X, //x重复
    REPEAT_Y  //y重复
}

class TestApp extends Canvas2DApplication {
    // 预定义颜色
    public static Colors: string[] = [
        'aqua',    //浅绿色
        'black',   //黑色
        'blue',    //蓝色 
        'fuchsia', //紫红色
        'gray',     //灰色
        'green',   //绿色
        'lime',    //绿黄色
        'maroon',  //褐红色
        'navy',    //海军蓝
        'olive',   //橄榄色
        'orange',  //橙色
        'purple',  //紫色
        'red',      //红色
        'silver',  //银灰色
        'teal',    //蓝绿色
        'yellow',   //黄色
        'white'   //白色
    ];


    // 渲染 绘制的内容
    public render() {
        if (this.context2D != null) {
            //清空画布
            this.context2D.clearRect(
                0, 0,
                this.canvas.width,
                this.canvas.height
            )
            // //绘制内容
            // this.context2D.fillStyle = "black";

            // this.context2D.fillRect(10,10,20,20);

            // this._drawRect(10, 10,
            //     this.canvas.width-20,
            //     this.canvas.height-20);

            // this.fillLinearRect(10, 10,
            //     this.canvas.width-20,
            //     this.canvas.height-20);

            // this.fillRadialRect(10, 10,
            //     this.canvas.width-20,
            //     this.canvas.height-20);

            // this.fillPatternRect(10, 10,
            //     this.canvas.width-20,
            //     this.canvas.height-20,
            //     "repeat"
            //     );

            // this.fillCircle(150,150,30,"blue")
            // this.strokeLine(
            //     20,20,
            //     150,180
            // )
            // this.context2D.strokeRect(
            //     20,20,
            //     50,50
            // )
            // this.strokeRect(
            //     60,60,
            //     30,30,
            //     "red"
            // )
            // this.strokeCoord(
            //     50,50,
            //     80,80
            // )
            // this.strokeGrid();

            // this.context2D.font = "50px sans-serif"
            // //绘制文本
            // this.context2D.fillText("Fill Text",15,50);
            // this.context2D.strokeText("Storke Text",15,150)
            // this.printTextStates()

            // this.fillText("Hello Font",15,15);
            // this.fillText("Hello Font",15,15,
            //     "center"
            // );
            // this.printTextStates()
            // this.testCanvaseTextLayout();
            // let url = "./data/test.jpg";
            // this.loadAndDrawImage(url);
        }
    }
    printLineStates() {
        if (this.context2D !== null) {
            console.log("*************LineState************")
            console.log("lineWidth", this.context2D.lineWidth);
            console.log("lineCap", this.context2D.lineCap);
            console.log("lineJoin", this.context2D.lineJoin)
            console.log("miterLimit", this.context2D.miterLimit);
        }
    }
    printTextStates() {
        if (this.context2D !== null) {
            console.log("*************TextState************")
            console.log("font-->", this.context2D.font);
            console.log("align-->", this.context2D.textAlign);
            console.log("baseLine-->", this.context2D.textBaseline)
        }
    }
    // 绘制方法
    private _drawRect(x: number, y: number,
        w: number, h: number) {
        if (this.context2D !== null) {
            //1 保存渲染状态
            this.context2D.save();
            //2 设置渲染状态相关属性
            // this.context2D.fillStyle = TestApp.Colors[0];
            // this.context2D.fillStyle = "rgb(255,0,0)";
            // this.context2D.fillStyle = "rgba(255,0,0,0.5)";
            // this.context2D.fillStyle = "rgb(100%,0%,0%)";
            this.context2D.fillStyle = "#ff00ff";

            this.context2D.strokeStyle = "blue";

            this.context2D.lineWidth = 20;
            // 线段属性
            // this.context2D.lineCap = "butt"
            // this.context2D.lineCap = "round"
            // this.context2D.lineCap = "square"

            // this.context2D.lineJoin="miter"
            // this.context2D.lineJoin = "bevel"
            // this.context2D.lineJoin = "round"
            // 虚线属性
            this.context2D.setLineDash([30, 15])
            this.context2D.lineDashOffset = this._lineDashOffset;

            //3 开始绘制路径
            this.context2D.beginPath();
            //4 添加需要绘制的点
            this.context2D.moveTo(x, y);
            this.context2D.lineTo(x + w, y);
            this.context2D.lineTo(x + w, y + h);
            this.context2D.lineTo(x, y + h)
            //5 结束绘制路径
            this.context2D.closePath();

            //6 描边或者填充
            this.context2D.fill();
            this.context2D.stroke();

            //7 恢复渲染状态
            this.context2D.restore();
        }
    }



    private _lineDashOffset = 0;
    private _updateDash() {
        this._lineDashOffset = this._lineDashOffset + 1;
        if (this._lineDashOffset > 10000) {
            this._lineDashOffset = 0;
        }
    }
    timerCallback(id: number, data: any) {
        this._updateDash();
        this._drawRect(10, 10,
            this.canvas.width, this.canvas.height
        )
    }
    start() {
        this.addTimer(
            (id: number, data: any) => {
                this.timerCallback(id, data)
            }, 0.05
        )
        super.start();
    }

    // 线性渐变色
    private _linearColor: CanvasGradient | undefined;
    fillLinearRect(
        x: number,
        y: number,
        w: number,
        h: number
    ) {
        if (this.context2D !== null) {
            this.context2D.save();
            if (this._linearColor == undefined) {
                // this._linearColor = this.context2D.createLinearGradient(
                //     x,y,
                //     x+w,y
                // )
                // this._linearColor = this.context2D.createLinearGradient(
                //     x+w,y,
                //     x,y
                // )
                this._linearColor = this.context2D.createLinearGradient(
                    x, y,
                    x + w, y + h
                )
                this._linearColor.addColorStop(0.0, "grey");
                this._linearColor.addColorStop(0.25, "rgba(255,0,0,1)");
                this._linearColor.addColorStop(0.5, "green")
                this._linearColor.addColorStop(0.75, "#0000ff")
                this._linearColor.addColorStop(1, "black")
            }
            this.context2D.fillStyle = this._linearColor;
            // 
            this.context2D.beginPath();
            this.context2D.rect(x, y, w, h);
            this.context2D.fill();

            this.context2D.restore();
        }
    }

    private _radialColor: CanvasGradient | undefined;
    fillRadialRect(
        x: number,
        y: number,
        w: number,
        h: number
    ) {
        if (this.context2D !== null) {
            this.context2D.save();
            if (this._radialColor == undefined) {
                let centX = x + 0.5 * w;
                let centY = y + 0.5 * h

                let radius = 0.5 * Math.min(w, h);
                // this._radialColor = this.context2D.createRadialGradient(
                //     centX,centY,0.3*radius,
                //     centX,centY,radius
                // )
                this._radialColor = this.context2D.createRadialGradient(
                    centX, centY, 0.5 * radius,
                    centX, centY, radius
                )

                this._radialColor.addColorStop(0.0, "black");
                this._radialColor.addColorStop(0.25, "rgba(255,0,0,1)")
                this._radialColor.addColorStop(0.5, "green");
                this._radialColor.addColorStop(0.75, "#0000ff");
                this._radialColor.addColorStop(1, "white")

            }
            this.context2D.fillStyle = this._radialColor;
            // 
            this.context2D.beginPath();
            this.context2D.rect(x, y, w, h);
            this.context2D.fill();

            this.context2D.restore();
        }
    }

    private _patternColor: CanvasPattern | undefined

    fillPatternRect(
        x: number,
        y: number,
        w: number,
        h: number,
        reapt: Repeatition = "repeat"
    ) {
        if (this.context2D !== null) {
            this.context2D.save();
            if (this._patternColor == undefined) {
                let img = document.createElement("img");
                img.src = "./data/test.jpg";
                img.onload = () => {
                    this._patternColor = this.context2D?.createPattern(img, reapt) as CanvasPattern;

                    if (this.context2D !== null) {

                        this.context2D.fillStyle = this._patternColor;
                        // 
                        this.context2D.beginPath();
                        this.context2D.rect(x, y, w, h);
                        this.context2D.fill();

                        this.context2D.restore();

                    }
                }

            } else {
                this.context2D.fillStyle = this._patternColor;
                // 
                this.context2D.beginPath();
                this.context2D.rect(x, y, w, h);
                this.context2D.fill();

                this.context2D.restore();
            }

        }
    }

    // 常见几何图形绘制
    // 点和圆
    fillCircle(
        x: number,
        y: number,
        radius: number = 3,
        fillStyle: string | CanvasGradient | CanvasPattern = "red"
    ) {
        if (this.context2D !== null) {
            this.context2D.save();

            this.context2D.fillStyle = fillStyle;
            this.context2D.beginPath();

            this.context2D.arc(x, y, radius, 0, Math.PI * 2)
            this.context2D.fill();

            this.context2D.restore();
        }
    }

    strokeLine(
        x0: number,
        y0: number,
        x1: number,
        y1: number
    ) {
        if (this.context2D !== null) {
            this.context2D.save();

            this.context2D.beginPath();

            this.context2D.moveTo(x0, y0);
            this.context2D.lineTo(x1, y1);
            this.context2D.stroke();

            this.context2D.restore();
        }
    }

    public strokeRect(
        x: number,
        y: number,
        w: number,
        h: number,
        color: string = 'black'): void {
        if (this.context2D !== null) {
            this.context2D.save();
            this.context2D.strokeStyle = color;
            this.context2D.beginPath();
            this.context2D.moveTo(x, y);
            this.context2D.lineTo(x + w, y);
            this.context2D.lineTo(x + w, y + h);
            this.context2D.lineTo(x, y + h);
            this.context2D.closePath();
            this.context2D.stroke();
            this.context2D.restore();
        }
    }

    strokeCoord(
        orginX: number,
        orginY: number,
        width: number,
        height: number
    ) {
        if (this.context2D !== null) {
            this.context2D.save();

            this.context2D.strokeStyle = "red";
            this.strokeLine(orginX, orginY, orginX + width, orginY);

            this.context2D.strokeStyle = "blue";
            this.strokeLine(orginX, orginY, orginX, orginY + height);

            this.context2D.restore();
        }
    }

    strokeGrid(
        color: string = "grey",
        interval: number = 10
    ) {
        if (this.context2D !== null) {
            this.context2D.save();

            this.context2D.strokeStyle = color;

            for (let i = interval + 0.5; i < this.canvas.width; i = i + interval) {
                this.strokeLine(i, 0, i, this.canvas.height)
            }

            for (let i = interval + 0.5; i < this.canvas.height; i = i + interval) {
                this.strokeLine(0, i, this.canvas.width, i)
            }

            this.context2D.restore();

            this.fillCircle(0, 0, 5, "green");
            this.strokeCoord(0, 0, this.canvas.width, this.canvas.height)
        }
    }


    fillText(
        text: string,
        x: number,
        y: number,
        color: string = "red",
        align: TextAlign = "left",
        baseline: TextBaseline = "top",
        font: string = this.makeFontString("20px")
    ) {
        if (this.context2D != null) {
            this.context2D.save();

            // 设置属性
            this.context2D.fillStyle = color;
            this.context2D.font = font;
            this.context2D.textAlign = align;
            this.context2D.textBaseline = baseline;
            this.context2D.fillText(text, x, y);

            this.context2D.restore();
        }
    }

    makeFontString(
        size: FontSize = "10px",
        weight: FontWeight = "normal",
        style: FontStyle = "normal",
        variant: FontVariant = "normal",
        family: FontFamily = "sans-serif"
    ) {
        let strs: string[] = [];

        strs.push(style);
        strs.push(variant);
        strs.push(weight);
        strs.push(size);
        strs.push(family);

        return strs.join(" ")
    }

    testCanvaseTextLayout() {

        this.strokeGrid();

        let x = 20
        let y = 20

        let width = this.canvas.width - 2 * x
        let height = this.canvas.height - 2 * y;
        // this.context2D?.fillRect(x,y,width,height)
        let centerX = x + 0.5 * width
        let centerY = y + 0.5 * height

        let right = x + width;
        let bottom = y + height;

        // 9个点
        let drawX = x;
        let drawY = y;
        this.fillCircle(drawX, drawY);
        this.fillText(
            "left-top", drawX, drawY,
            "red", "left", "top"
        )
        drawX = centerX;
        drawY = y;
        this.fillCircle(drawX, drawY);
        this.fillText(
            "center-top", drawX, drawY,
            "black", "center", "top"
        )

        drawX = right
        drawY = y;
        this.fillCircle(drawX, drawY);
        this.fillText(
            "right-top", drawX, drawY,
            "red", "right", "top"
        )


        drawX = right
        drawY = centerY
        this.fillCircle(drawX, drawY);
        this.fillText(
            "right-middle", drawX, drawY,
            "red", "right", "middle"
        )

        drawX = right;
        drawY = bottom;
        this.fillCircle(drawX, drawY);
        this.fillText(
            "right-bottom", drawX, drawY,
            "red", "right", "bottom"
        )

        drawX = centerX;
        drawY = bottom;
        this.fillCircle(drawX, drawY);
        this.fillText(
            "center-bottom", drawX, drawY,
            "black", "center", "bottom"
        )

        drawX = x;
        drawY = bottom
        this.fillCircle(drawX, drawY);
        this.fillText(
            "left-bottom", drawX, drawY,
            "red", "left", "bottom"
        )

        drawX = x
        drawY = centerY
        this.fillCircle(drawX, drawY);
        this.fillText(
            "left-middle", drawX, drawY,
            "red", "left", "middle"
        )

        drawX = centerX;
        drawY = centerY;
        this.fillCircle(drawX, drawY)
        this.fillText(
            "center-middle", drawX, drawY,
            "black", "center", "middle"
        )
    }

    loadAndDrawImage(
        url: string
    ) {
        //首先加载图像
        let img = document.createElement("img");
        img.src = url;
        img.onload = (evt) => {
            //
            console.log("img", img, img.width, img.height)
            if (this.context2D != null) {
                // 1 简单绘制
                // this.context2D.drawImage(img, 10, 10)

                // 2 缩放 dw,dh 控制绘制目标的缩放
                // let s = 1.5;
                // this.context2D.drawImage(img,10,10,s*img.width,s*img.height)

                // 3 原图像部分绘制 sx,sy,sw,sh
                // this.context2D.drawImage(img,
                //     100,100,100,100,    //src
                //     300,300,100,100   //dst
                // )

                // this.drawImage(
                //     img, 
                //     Rectangle.create(10, 10, this.canvas.width, this.canvas.height),
                //     Rectangle.create(0, 0, img.width, img.height),
                //     EImageFillType.REPEAT_X
                // )

                // this.drawImage(
                //     img, 
                //     Rectangle.create(10, 10, this.canvas.width, this.canvas.height),
                //     Rectangle.create(0, 0, img.width, img.height),
                //     EImageFillType.REPEAT_Y
                // )

                this.drawImage(
                    img,
                    Rectangle.create(10, 10, this.canvas.width, this.canvas.height),
                    Rectangle.create(50, 50, 100, 100),
                    EImageFillType.REPEAT
                )

                // Tile 2d地图绘制
            }
        }
    }


    drawImage(
        img: HTMLImageElement | HTMLCanvasElement,
        destRect: Rectangle,
        srcRect = Rectangle.create(0, 0, img.width, img.height),
        fillType = EImageFillType.STRETCH
    ) {
        //绘制
        if (this.context2D != null) {
            //判定src
            if (fillType == EImageFillType.STRETCH) {
                this.context2D.drawImage(
                    img,
                    srcRect.origin.x, srcRect.origin.y,
                    srcRect.size.width, srcRect.size.height,
                    destRect.origin.x, destRect.origin.y,
                    destRect.size.width, destRect.size.height,
                )
            } else {
                //Repeat,Repeat-x,Repeat-Y
                //计算出取整的
                let rows = Math.ceil(
                    destRect.size.width / srcRect.size.width,
                )
                let columns = Math.ceil(
                    destRect.size.height / srcRect.size.height,
                )

                if (fillType == EImageFillType.REPEAT_X) { //x
                    columns = 1
                } else if (fillType == EImageFillType.REPEAT_Y) { //y
                    rows = 1;
                }
                // 记录当前绘制信息
                let left = 0, top = 0;

                let width = srcRect.size.width;
                let height = srcRect.size.height;

                console.log("row,col", rows, columns)

                // 循环输出rows,columns
                for (let i = 0; i < rows; i++) {
                    for (let j = 0; j < columns; j++) {
                        // 左上顶点
                        left = destRect.origin.x + i * srcRect.size.width;
                        top = destRect.origin.y + j * srcRect.size.height;

                        console.log("x,y", left, top)

                        this.context2D.drawImage(
                            img,
                            srcRect.origin.x,
                            srcRect.origin.y,
                            width, height,
                            left, top, width, height
                        )

                    }
                }
            }
        }
    }

    drawColorCanvas() {
        //读取canvas的颜色
        let colorCanvas = this.getColorCanvas();
        console.log("canvas", colorCanvas.width, colorCanvas.height)

        //drawImage()
        this.drawImage(
            colorCanvas,
            Rectangle.create(10, 10, colorCanvas.width, colorCanvas.height)
        )

        this.testChangeCanvas();
    }
    testChangeCanvas(
        // (0,2)蓝色块
        rRow = 2,
        rColum = 0,
        // (0,1)黑色块 
        cRow = 1,
        cColum = 0,

        size = 32
    ) {
        let colorCanvas = this.getColorCanvas(size);
        let ctx = colorCanvas.getContext("2d");
        if (ctx != null) {
            //准备绘制目标块(32x32)
            let imgData = ctx.createImageData(size, size);
            let data = imgData.data;

            let rbgaCount = data.length / 4;
            console.log("img", imgData, rbgaCount);

            //填充颜色 32x32 (0,2)蓝色块的替换成红色
            for (let i = 0; i < rbgaCount; i++) {
                data[i * 4 + 0] = 255; //r
                data[i * 4 + 1] = 0;   //g
                data[i * 4 + 2] = 0;   //b
                data[i * 4 + 3] = 255; //a
            }

            //修改目标的区域
            ctx.putImageData(
                imgData, //需要修改的颜色数据
                size * rColum, size * rRow, //目标坐标
                0, 0,      //颜色源的坐标
                size, size //颜色源的宽和高
            )

            //(0,1)黑色块->白色 
            //  for(let i =0;i<rbgaCount;i++){
            //     data[i*4 + 0] = 255; //r
            //     data[i*4 + 1] = 255;   //g
            //     data[i*4 + 2] = 255;   //b
            //     data[i*4 + 3] = 255; //a
            // }

            //修改目标的区域
            // ctx.putImageData(
            //     imgData, //需要修改的颜色数据
            //     size*cColum,size*cRow, //目标坐标
            //     0,0,      //颜色源的坐标
            //     size,size //颜色源的宽和高
            // )

            //使用getImageData()
            imgData = ctx.getImageData(
                size * cColum,
                size * cRow,
                size, size
            )
            data = imgData.data;
            let component = 0;
            // for (let i = 0; i < imgData.width; i++) {
            //     for (let j = 0; i < imgData.height; j++) {
            //         //像素块的遍历
            //         for (let k = 0; k < 4; k++) {
            //             //rgba
            //             let idx = (i * imgData.height + j) * 4 + k;
            //             //r g b a的颜色数据
            //             component = data[idx];
            //             if (idx % 4 == 3) {
            //                 data[idx] = 255 - component;
            //             }
            //         }
            //     }
            // }
            ctx.putImageData(
                imgData, //需要修改的颜色数据
                size * cColum, size * cRow, //目标坐标
                0, 0,      //颜色源的坐标
                size, size //颜色源的宽和高
            )
        }

        this.drawImage(
            colorCanvas,
            Rectangle.create(300, 10,
                colorCanvas.width, colorCanvas.height)
        )
    }
    // 读取Canvas的颜色组成
    getColorCanvas(
        amount = 32
    ) {
        let canvas = document.createElement("canvas");
        let step = 4; //水平和垂直的块的个数
        //amount 每个块的宽和高
        canvas.width = step * amount;
        canvas.height = step * amount;

        let context = canvas.getContext("2d");
        if (context != null) {
            for (let i = 0; i < step; i++) {
                for (let j = 0; j < step; j++) {
                    let idx = step * i + j;
                    context.save();
                    //
                    context.fillStyle = TestApp.Colors[idx];

                    context.fillRect(
                        i * amount, j * amount,
                        amount, amount
                    )
                    context.restore();
                }
            }
            //画布的颜色数据
            // let imgData = context.getImageData(
            //     0,0,
            //     canvas.width,
            //     canvas.height
            // )
            // console.log("imgData",imgData);
        }


        return canvas;
    }

}

export {
    TestApp,
    TextAlign,
    TextBaseline
}